package com.yichen.ycapi.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yichen.ycapi.common.ErrorCode;
import com.yichen.ycapi.constant.CommonConstant;
import com.yichen.ycapi.exception.BusinessException;
import com.yichen.ycapi.exception.ThrowUtils;
import com.yichen.ycapi.mapper.UserInterfaceInfoMapper;
import com.yichen.ycapi.model.dto.userInterfaceInfo.UserInterfaceInfoQueryRequest;
import com.yichen.ycApiCommon.model.entity.InterfaceInfo;
import com.yichen.ycApiCommon.model.entity.User;
import com.yichen.ycApiCommon.model.entity.UserInterfaceInfo;
import com.yichen.ycapi.model.enums.InterfaceStatusEnum;
import com.yichen.ycapi.model.vo.InterfaceInfoVO;
import com.yichen.ycapi.model.vo.UserInterfaceInfoVO;
import com.yichen.ycapi.model.vo.UserVO;
import com.yichen.ycapi.service.InterfaceInfoService;
import com.yichen.ycapi.service.UserInterfaceInfoService;
import com.yichen.ycapi.service.UserService;
import com.yichen.ycapi.utils.SqlUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @description 针对表【user_interface_info(用户调用接口关系)】的数据库操作Service实现
 * @createDate 2024-07-30 02:11:41
 */
@Service
public class UserInterfaceInfoServiceImpl extends ServiceImpl<UserInterfaceInfoMapper, UserInterfaceInfo>
        implements UserInterfaceInfoService {

    @Resource
    private UserService userService;

    @Resource
    private InterfaceInfoService interfaceInfoService;

    /**
     * 校验接口
     *
     * @param userInterfaceInfo
     * @param add
     */
    @Override
    public void validUserInterfaceInfo(UserInterfaceInfo userInterfaceInfo, boolean add) {
        if (userInterfaceInfo == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long id = userInterfaceInfo.getId();
        Long userId = userInterfaceInfo.getUserId();
        Long interfaceInfoId = userInterfaceInfo.getInterfaceInfoId();
        Integer totalNum = userInterfaceInfo.getTotalNum();
        Integer leftNum = userInterfaceInfo.getLeftNum();


        // 创建时，参数不能为空
        if (add) {
            ThrowUtils.throwIf(ObjectUtils.isEmpty(id), ErrorCode.PARAMS_ERROR);
            ThrowUtils.throwIf(ObjectUtils.isEmpty(userId), ErrorCode.PARAMS_ERROR);
            ThrowUtils.throwIf(ObjectUtils.isEmpty(interfaceInfoId), ErrorCode.PARAMS_ERROR);
            ThrowUtils.throwIf(totalNum < 0 || leftNum < 0, ErrorCode.PARAMS_ERROR);

        }
        // 有参数则校验
        User user = new User();
        user.setId(userId);
        InterfaceInfo interfaceInfo = new InterfaceInfo();
        interfaceInfo.setId(interfaceInfoId);
        if (ObjectUtils.isEmpty(userService.getById(user))) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在");
        }
        InterfaceInfo byId = interfaceInfoService.getById(interfaceInfo);
        if (ObjectUtils.isEmpty(byId) || byId.getStatus().equals(InterfaceStatusEnum.OFFLINE.getValue())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "接口不存在或接口已下线");
        }
    }

    /**
     * 获取查询包装类
     *
     * @param userInterfaceInfoQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<UserInterfaceInfo> getQueryWrapper(UserInterfaceInfoQueryRequest userInterfaceInfoQueryRequest) {
        QueryWrapper<UserInterfaceInfo> queryWrapper = new QueryWrapper<>();
        if (userInterfaceInfoQueryRequest == null) {
            return queryWrapper;
        }
        Long id = userInterfaceInfoQueryRequest.getId();
        Long userId = userInterfaceInfoQueryRequest.getUserId();
        Long interfaceInfoId = userInterfaceInfoQueryRequest.getInterfaceInfoId();
        Integer totalNum = userInterfaceInfoQueryRequest.getTotalNum();
        Integer leftNum = userInterfaceInfoQueryRequest.getLeftNum();
        Integer status = userInterfaceInfoQueryRequest.getStatus();
        String sortField = userInterfaceInfoQueryRequest.getSortField();
        String sortOrder = userInterfaceInfoQueryRequest.getSortOrder();


        // 拼接查询条件
        queryWrapper.ne(ObjectUtils.isNotEmpty(status), "status", status);
        queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(interfaceInfoId), "interfaceInfoId", interfaceInfoId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(totalNum), "totalNum", totalNum);
        queryWrapper.eq(ObjectUtils.isNotEmpty(leftNum), "leftNum", leftNum);
        queryWrapper.eq(ObjectUtils.isNotEmpty(interfaceInfoId), "interfaceInfoId", interfaceInfoId);
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return queryWrapper;
    }

    @Override
    public UserInterfaceInfoVO getUserInterfaceInfoVO(UserInterfaceInfo userInterfaceInfo, HttpServletRequest request) {
        UserInterfaceInfoVO userInterfaceInfoVO = UserInterfaceInfoVO.objToVo(userInterfaceInfo);
        // 1. 关联查询用户信息
        Long userId = userInterfaceInfo.getUserId();
        User user = null;
        if (userId != null && userId > 0) {
            user = userService.getById(userId);
        }
        Long interfaceInfoId = userInterfaceInfo.getInterfaceInfoId();
        InterfaceInfo interfaceInfo = null;
        if (interfaceInfoId != null && interfaceInfoId > 0) {
            interfaceInfo = interfaceInfoService.getById(interfaceInfoId);
        }
        UserVO userVO = userService.getUserVO(user);
//        InterfaceInfoVO interfaceInfoVO = interfaceInfoService.getInterfaceInfoVO(interfaceInfo, request);
        userInterfaceInfoVO.setUserVO(userVO);
//        userInterfaceInfoVO.setInterfaceInfoVO(interfaceInfoVO);
        return userInterfaceInfoVO;
    }

    @Override
    public Page<UserInterfaceInfoVO> getUserInterfaceInfoVOPage(Page<UserInterfaceInfo> userInterfaceInfoPage, HttpServletRequest request) {
        List<UserInterfaceInfo> userInterfaceInfoList = userInterfaceInfoPage.getRecords();
        Page<UserInterfaceInfoVO> userInterfaceInfoVOPage = new Page<>(userInterfaceInfoPage.getCurrent(), userInterfaceInfoPage.getSize(), userInterfaceInfoPage.getTotal());
        if (CollUtil.isEmpty(userInterfaceInfoList)) {
            return userInterfaceInfoVOPage;
        }
        // 1. 关联查询用户信息
        Set<Long> userIdSet = userInterfaceInfoList.stream().map(UserInterfaceInfo::getUserId).collect(Collectors.toSet());
        Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
                .collect(Collectors.groupingBy(User::getId));

        Set<Long> interfaceInfoIdSet = userInterfaceInfoList.stream().map(UserInterfaceInfo::getInterfaceInfoId).collect(Collectors.toSet());
        Map<Long, List<InterfaceInfo>> interfaceInfoInterfaceInfoMap = interfaceInfoService.listByIds(interfaceInfoIdSet).stream()
                .collect(Collectors.groupingBy(InterfaceInfo::getId));

        // 填充信息
        List<UserInterfaceInfoVO> userInterfaceInfoVOList = userInterfaceInfoList.stream().map(userInterfaceInfo -> {
            UserInterfaceInfoVO userInterfaceInfoVO = UserInterfaceInfoVO.objToVo(userInterfaceInfo);
            Long userId = userInterfaceInfo.getUserId();
            User user = null;
            if (userIdUserListMap.containsKey(userId)) {
                user = userIdUserListMap.get(userId).get(0);
            }
            userInterfaceInfoVO.setUserVO(userService.getUserVO(user));
            Long interfaceInfoId = userInterfaceInfo.getInterfaceInfoId();
            InterfaceInfo interfaceInfo = null;
            if (userIdUserListMap.containsKey(interfaceInfoId)) {
                interfaceInfo = interfaceInfoInterfaceInfoMap.get(interfaceInfoId).get(0);
            }
//            userInterfaceInfoVO.setInterfaceInfoVO(interfaceInfoService.getInterfaceInfoVO(interfaceInfo, request));
            return userInterfaceInfoVO;
        }).collect(Collectors.toList());
        userInterfaceInfoVOPage.setRecords(userInterfaceInfoVOList);
        return userInterfaceInfoVOPage;
    }

    /**
     * 调用接口次数加一
     *
     * @param interfaceInfoId
     * @param userId
     * @return
     */
    @Override
    public Boolean invokeCountPlus(Long interfaceInfoId, Long userId) {
        // todo : 给接口加上事务保持一致性，加锁
        Boolean flag = false;
        // 校验
        if (interfaceInfoId <= 0 || userId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User user = new User();
        user.setId(userId);
        if (ObjectUtils.isEmpty(userService.getById(user))) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在");
        }
        InterfaceInfo interfaceInfo = new InterfaceInfo();
        interfaceInfo.setId(interfaceInfoId);
        InterfaceInfo byId = interfaceInfoService.getById(interfaceInfo);
        if (ObjectUtils.isEmpty(byId) || byId.getStatus().equals(InterfaceStatusEnum.OFFLINE.getValue())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "接口不存在或接口已下线");
        }

        UserInterfaceInfo userInterfaceInfo = this.getOne(new QueryWrapper<UserInterfaceInfo>()
                .eq("interfaceInfoId", interfaceInfoId)
                .eq("userId", userId));
        if (ObjectUtils.isEmpty(userInterfaceInfo)) {
            userInterfaceInfo.setUserId(userId);
            userInterfaceInfo.setInterfaceInfoId(interfaceInfoId);
            userInterfaceInfo.setTotalNum(1);
            flag = this.save(userInterfaceInfo);
            ThrowUtils.throwIf(!flag, ErrorCode.OPERATION_ERROR, "新建数据库调用次数失败");
        } else {
            flag = this.update(new UpdateWrapper<UserInterfaceInfo>()
                    .eq("interfaceInfoId", interfaceInfoId)
                    .eq("userId", userId)
                    .setSql("leftNum = leftNum - 1, totalNum = totalNum + 1")
            );
            ThrowUtils.throwIf(!flag, ErrorCode.OPERATION_ERROR, "修改数据库调用次数失败");
        }
        return flag;
    }
}




